package com.dcloud.core.innerDBOperate.impl;

import com.dcloud.core.client.IClient;
import com.dcloud.core.innerDBOperate.InnerDBOperateService;
import com.dcloud.core.source.RdbmsSource;
import com.dcloud.dbdrive.IClientFactory;
import com.dcloud.enums.BizErrorEnum;
import com.dcloud.exception.BizException;
import com.dcloud.manage.dblib.entity.DatalibLogicTable;
import com.dcloud.manage.dblib.entity.vo.DatalibLogicActVO;
import com.dcloud.manage.dblib.entity.vo.DatalibTableExtVO;
import com.dcloud.manage.service.ICollectSourceService;
import com.dcloud.manage.service.entity.DBInfoEntity;
import com.dcloud.manage.service.entity.DBParamsEntity;
import com.dcloud.utils.ClassUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * @ClassName : InnerDBOperateServiceImpl
 * @Description :
 * @Author : shijf
 * @Date: 2024-08-15 15:47
 */
@Slf4j
@Service
public class InnerDBOperateServiceImpl implements InnerDBOperateService {
    
    @Autowired
    private ICollectSourceService iCollectSourceService;

    @Autowired
    IClientFactory iClientFactory;


    @Override
    public void createTable(DatalibLogicTable datalibLogicTable, List<DatalibLogicActVO> listByTableId, DatalibTableExtVO datalibTableExtVO) {
        //根据数据源不同，组装SQL
        DBInfoEntity dbInfoEntity = iCollectSourceService.queryDbInfoBySourceTid(datalibLogicTable.getTableSourceId());

        //拼接建表语句
        StringBuilder createTableSql = new StringBuilder();
        //1.创建表
        createTableSql.append("CREATE TABLE IF NOT EXISTS "+datalibLogicTable.getTableCode()+" ( \n");
        //2.创建字段
        int i = 0;
        int length = listByTableId.size();
        for (DatalibLogicActVO datalibLogicActVO : listByTableId) {
            i++;
            String dataType = datalibLogicActVO.getLogicDataType(); //字段类型
            Integer logicDataLength = datalibLogicActVO.getLogicDataLength();
            Integer logicDataDecimal = datalibLogicActVO.getLogicDataDecimal();
            String decimalStr = logicDataDecimal == null ? "" : (","+logicDataDecimal);
            String lengthStr = logicDataLength == null ? "" : ("("+logicDataLength+decimalStr+")");

            String comment = StringUtils.isNotEmpty(datalibLogicActVO.getLogicName()) ? "" : " COMMENT '"+datalibLogicActVO.getLogicName()+"'";


            createTableSql.append(" `"+datalibLogicActVO.getLogicCode()+"` "+dataType+lengthStr+comment+(i<length ? "," : " ") +"  \n");
        }

        //3.创建引擎
        createTableSql.append(") ENGINE=OLAP \n");
        //4.创建扩展信息
        String keys = String.join(",",Arrays.stream(datalibTableExtVO.getKeyCodes().split(",")).map(e -> "`"+e+"`").collect(Collectors.toList()));
        createTableSql.append("DUPLICATE KEY("+keys+") \n");
        createTableSql.append("COMMENT '"+datalibLogicTable.getTableName()+"' \n");

        //判断分区字段类型
        if(Strings.isNotEmpty(datalibTableExtVO.getPartitionKey())){
            String partitionKey = datalibTableExtVO.getPartitionKey();
            String partitionType = listByTableId.stream().filter(e -> e.getLogicCode().equals(partitionKey)).findFirst().get().getLogicDataType();
            if(StringUtils.equals(partitionType,"DATE") || StringUtils.equals(partitionType,"DATETIME")){
                createTableSql.append(" AUTO PARTITION BY RANGE (date_trunc(`"+partitionKey+"`, '"+datalibTableExtVO.getPartitionDataType()+"')) \n" +
                        "( \n" +
                        ") \n");
            }else{
                createTableSql.append(" AUTO PARTITION BY LIST (`"+partitionKey+"`)() \n");
            }
        }

        //自动分桶
        createTableSql.append(" DISTRIBUTED BY HASH("+datalibTableExtVO.getDisKey()+") BUCKETS AUTO \n" +
                "properties(\"estimate_partition_size\" = \"2G\",\"replication_num\"=\"1\") ");



        log.info(createTableSql.toString());


        //获取数据源
        //查询任务sql的数据源信息
        Map<String, List<DBParamsEntity>> collect = dbInfoEntity.getList().stream().collect(groupingBy(DBParamsEntity::getParamCode));
        //反射构建source类,将数据表参数值根据反射set 插入到对象中
        try {
            Class<?> aClass  = Class.forName(dbInfoEntity.getClassLoad());
            RdbmsSource defineSource = (RdbmsSource) aClass.newInstance();
            Field[] allFields = ClassUtils.getAllFields(aClass);
            for(Field field : allFields){
                if(collect.containsKey(field.getName())){
                    String paramValue = collect.get(field.getName()).get(0).getParamValue();
                    field.setAccessible(true);
                    field.set(defineSource,paramValue);
                }
            }

            //获取客户端
            IClient client = iClientFactory.getDbdriveByCode(dbInfoEntity.getSourceCode());
            //建表
            client.createTable(defineSource,createTableSql.toString());
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BizException(BizErrorEnum.DATALIB_ERROR_CREATE_TABLE.getCode(),BizErrorEnum.DATALIB_ERROR_CREATE_TABLE.getErrorMsg()+",表名"+datalibLogicTable.getTableCode());
        }

    }

    @Override
    public List<Map<String, Object>> jxcx(DatalibLogicTable datalibLogicTable, String sql, Long pageNo, Long pageSize) {
        //获取数据源
        DBInfoEntity dbInfoEntity = iCollectSourceService.queryDbInfoBySourceTid(datalibLogicTable.getTableSourceId());

        //查询任务sql的数据源信息
        Map<String, List<DBParamsEntity>> collect = dbInfoEntity.getList().stream().collect(groupingBy(DBParamsEntity::getParamCode));
        //反射构建source类,将数据表参数值根据反射set 插入到对象中
        try {
            Class<?> aClass  = Class.forName(dbInfoEntity.getClassLoad());
            RdbmsSource defineSource = (RdbmsSource) aClass.newInstance();
            Field[] allFields = ClassUtils.getAllFields(aClass);
            for(Field field : allFields){
                if(collect.containsKey(field.getName())){
                    String paramValue = collect.get(field.getName()).get(0).getParamValue();
                    field.setAccessible(true);
                    field.set(defineSource,paramValue);
                }
            }

            //获取客户端
            IClient client = iClientFactory.getDbdriveByCode(dbInfoEntity.getSourceCode());
            //建表

            Long count =  client.execQueryCount(defineSource,sql);
            int totalPages = (int) Math.ceil( count / pageSize)+1; // 计算总页数
            Long currentPage = pageNo; // 获取当前页码
            if (currentPage < 1) {
                currentPage = (Long) 1L; // 最小页码为1
            } else if (currentPage > totalPages) {
                currentPage = Long.valueOf(String.valueOf(totalPages)); // 最大页码限制为总页数
            }
            Long offset = (Long) ((currentPage - 1) * pageSize);


            List<Map<String,Object>> list = client.execQueryWithLimit(defineSource, sql, offset, pageSize);
            return list;
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BizException(BizErrorEnum.DATALIB_ERROR_TABLE_JXCX.getCode(),BizErrorEnum.DATALIB_ERROR_TABLE_JXCX.getErrorMsg()+",表名"+datalibLogicTable.getTableCode());
        }
    }

    @Override
    public String ddlInfo(String table,Integer tableId) {
        //获取数据源
        DBInfoEntity dbInfoEntity = iCollectSourceService.queryDbInfoBySourceTid(tableId);

        //查询任务sql的数据源信息
        Map<String, List<DBParamsEntity>> collect = dbInfoEntity.getList().stream().collect(groupingBy(DBParamsEntity::getParamCode));
        //反射构建source类,将数据表参数值根据反射set 插入到对象中
        try {
            Class<?> aClass  = Class.forName(dbInfoEntity.getClassLoad());
            RdbmsSource defineSource = (RdbmsSource) aClass.newInstance();
            Field[] allFields = ClassUtils.getAllFields(aClass);
            for(Field field : allFields){
                if(collect.containsKey(field.getName())){
                    String paramValue = collect.get(field.getName()).get(0).getParamValue();
                    field.setAccessible(true);
                    field.set(defineSource,paramValue);
                }
            }

            //获取客户端
            IClient client = iClientFactory.getDbdriveByCode(dbInfoEntity.getSourceCode());
            //建表

            List<Map<String,Object>> list = client.execQuery(defineSource, "show create table "+table );
            if(list.size() > 0){
                return list.get(0).get("Create Table").toString();
            }else{
                return null;
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BizException(BizErrorEnum.DATALIB_ERROR_TABLE_DDL.getCode(),BizErrorEnum.DATALIB_ERROR_TABLE_DDL.getErrorMsg()+",表名"+table);
        }
    }
}
